home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 25 / CU Amiga Magazine's Super CD-ROM 25 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-08].iso / CUCD / Magazine / C_Tutorial / Part-11 / req1 / fractal.c < prev    next >
C/C++ Source or Header  |  1998-04-05  |  3KB  |  122 lines

  1. #include "fractal.h"
  2.  
  3. #include<exec/tasks.h>
  4.  
  5. #include<stdlib.h>
  6. #include<stdio.h>
  7.  
  8. #include "gadgets.h"
  9.  
  10. #include<clib/alib_protos.h>
  11. #include<clib/exec_protos.h>
  12. #include<clib/graphics_protos.h>
  13.  
  14. static int calc(double, double, int);
  15. static void fractal(void);
  16.  
  17. /* The mechanism by which we will control our task: */
  18. /* One Semaphore for drawing, the other for running */
  19. static struct SignalSemaphore drawing;
  20. static struct SignalSemaphore running;
  21.  
  22. /* Initialisation done when program is started */
  23. void initSemaphores()
  24. {
  25.     InitSemaphore(&drawing);
  26.     InitSemaphore(&running);
  27. }
  28.  
  29. /* To stop the fractal we stop it drawing then stop our */
  30. /* task from running */
  31. void stopFractal()
  32. {
  33.     ObtainSemaphore(&drawing);
  34.     ObtainSemaphore(&running);
  35.     ReleaseSemaphore(&running);
  36.     ReleaseSemaphore(&drawing);
  37. }
  38.  
  39. /* A local copy of the window pointer for our task */
  40. static struct Window* win;
  41.  
  42. /* Draw a fractal in the window */
  43. void drawFractal(struct Window* w)
  44. {
  45.     /* If the semaphore is available a task is not already running */
  46.     if(AttemptSemaphore(&running))
  47.     {
  48.         struct Task* task;
  49.         ReleaseSemaphore(&running);
  50.         /* Make a copy of the window pointer for the task to use */
  51.         win = w;
  52.         /* Create a new task which will draw the fractal */
  53.         task = CreateTask("HelloPainter-Fractal",-1,&fractal,4096);
  54.         if(task == NULL)
  55.             printf("Error: could not create task\n");
  56.     }
  57.     else
  58.         /* The semaphore was already taken, so stop the task */
  59.         stopFractal();
  60. }
  61.  
  62. /* The starting point of our task */
  63. static void __saveds fractal()
  64. {
  65.     /* If the semaphore is available we can start running */
  66.   if(AttemptSemaphore(&running))
  67.   {
  68.         /* The width, height and number of colours for drawing */
  69.         int w=win->Width, h=win->Height, d=1<<win->WScreen->BitMap.Depth;
  70.         /* The snapshot of the mandelbrot set to draw */
  71.         /* (Adjust these numbers to draw different fractals) */
  72.         double width=4.0, height=4.0, top=-2.0, left=-2.5;
  73.         double* array = malloc(h*sizeof(double));
  74.         if(array)
  75.         {
  76.             int x;
  77.             /* Load the array with the vertical values */
  78.             for(x=0; x<h; x++)
  79.                 array[x]=x*height/h+top;
  80.             /* Check whether we can continue drawing on each x */
  81.             for(x=0; x<w && AttemptSemaphore(&drawing); x++)
  82.             {
  83.                 /* Precalculate the horizontal value */
  84.                 double xr = x*width/w+left;
  85.                 int y;
  86.                 for(y=0; y<h; y++)
  87.                 {
  88.                     /* Set the current colour, using our precalculated values */
  89.                     setFgPen(win, calc(xr,array[y],d));
  90.                     /* Draw the pixel */
  91.                     WritePixel(win->RPort,x,y);
  92.                 }
  93.                 /* Release the semaphore before checking again */
  94.                 ReleaseSemaphore(&drawing);
  95.             }
  96.             /* Now we've finished, release the memory from the malloc()ed array */
  97.             free(array);
  98.         }
  99.         /* Release the semaphore to indicate the task has finished */
  100.         ReleaseSemaphore(&running);
  101.     }
  102. }
  103.  
  104. /* Calculate the colour of a particular point */
  105. /* (This is the number of iterations of the equation */
  106. /* needed to exceed the bound value) */
  107. static int calc(double x, double y, int d)
  108. {
  109.     double xc=x, yc=y;
  110.     double xsq=x*x, ysq=y*y;
  111.     int it;
  112.     /* Adjust the 16.0 to give different colour spreads */
  113.     for(it=0; it<d && xsq+ysq<16.0; it++)
  114.     {
  115.         yc = 2.0*xc*yc+y;
  116.         xc = xsq-ysq+x;
  117.         xsq = xc*xc;
  118.         ysq = yc*yc;
  119.     }
  120.     return it;
  121. }
  122.